/**
 * Filename: GAInAppPurchaseHandler.js
 * Author: Harris Khurram
 * Updates: Abid Hussain
 * US SDK Integration : May 30, 2011 -- Harris  THIS FILE IS TESTED WITH US INTENT ONLY.
 * Date Created: 04-25-2011
 * Date Updated: 05-30-2011
 */

var GAPurchaseSyncHandler = require('./GAPurchaseSyncHandler').GAPurchaseSyncHandler;

exports.GAInAppPurchaseHandler = Core.Class.singleton({

    classname: 'GAInAppPurchaseHandler',
	
	initialize: function() {
		this._initStatusVars();
        this._loadDefaultUserMsgs();
        this._completedTransactions = null;
        this._txnStorage = new Storage.KeyValue();
        var myself = this;
        this._txnStorage.getItem(COMPLETED_TXN_KEY, 
        	function(error, value, key) {
        		if (!error && value != null) {
        			myself._completedTransactions = eval("(" + value + ")");
        		}
        		else {
					myself._completedTransactions = {};
        		}
        	}
        );
		setTimeout(this._loadUserMsgs.bind(this), 6000);
	},
	
	performInitialization: function(){
		/* do nothing - this will automatically call initialize */
	},

	performInAppWithItemIdAndCallback: function(anInAppItemId, aCallBack, aComment) {
		//by default we send quantity as 1
		this.performInAppWithItemIdQuantityAndCallback(anInAppItemId, 1, aCallBack, aComment);
	},
	
	performInAppWithItemIdQuantityAndCallback: function(anInAppItemId, aQuantity, aCallBack, aComment) {
		UIFactory.showProgressHUD(this._msg._contactingServer);
		UIFactory.showBlockView();

		if(isValidString(aQuantity)) {
			aQuantity = parseInt(aQuantity,10);
		} else if (isValidNumber(aQuantity)) {
			aQuantity = aQuantity;
		} else {
			//cannot understand quantity parameter
			aQuantity = -1
		}
		
		
		if(!isValidString(anInAppItemId) || typeof aCallBack != 'function' || aQuantity == -1 )
        {
			this._transactionFailure(GAInAppPurchase.noItem);
            UIFactory.hideBlockView();
            UIFactory.showToast("Wrong Parameters to Bank Method - GAPI");

			return;
		}
        
        if(!aComment)
        {
            aComment = " ";
        }
        
		
		var inAppItemId = anInAppItemId;
		this._quantity = "" + aQuantity   //converting to string
		this._callBack = aCallBack;
        this._msg._InAppComment = aComment;
		
		Bank.Inventory.getItem(inAppItemId, this._performInAppCallback.bind(this)); // FOR US SDK
		
		//Bank.Service.Banking.Inventory.getItem(inAppItemId, this._performInAppCallback.bind(this));
	},
	
    showMobageBalanceButton: function(uiGeometryRect) {
           var frame = null;
			if (uiGeometryRect instanceof UI.ViewGeometry.Rect){
					frame = uiGeometryRect;
			} else if (uiGeometryRect instanceof Array) {
				if (uiGeometryRect.length >=4) {
					frame = new UI.ViewGeometry.Rect(uiGeometryRect[0], uiGeometryRect[1],uiGeometryRect[2],uiGeometryRect[3]);
				} else {
					//console.log("GALogger: MobageBalance will use default values. for rect.");
				}
			} 
			
			if(frame == null) {
				//if frame is still null, load default values
				frame = new UI.ViewGeometry.Rect(0,0,200,80);
			}
		   Social.Common.Service.showBalanceButton(frame, function(error){});//THIS IS FOR CHINESE
		   //Social.US.Service.ButtonOverlays.showBalanceButton(frame, function(error){});////UNCOMMENT IT FOR US SDK 		
	},
	hideMobageBalanceButton: function() {
		//Social.US.Service.ButtonOverlays.hideBalanceButton(function(error) {});
		Social.Common.Service.hideBalanceButton(function(error) {});
	},
	
	$mobageTokushohoPolicy: function() {
        UIFactory.showToast("Policy button not implemented yet for US SDK.");
        return;
	},
    
    notifyServer: function(currencyType, amount) {
		var signature = this._getSignature(currencyType, amount);
		var requestUrl = this._getRequestUrl(currencyType, amount, signature);
		var webFetcher = new GAWebFetcher(this, 30, 0);
		webFetcher.invokeGetRequest(requestUrl);
	},


    _initStatusVars: function() {
		this._confirmedTransactionId = null;
		this._callBack = null;
		this._errorMsg = null;
		this._retryCount = 9;
		this._quantity = -1;
	},
    
    
    _loadDefaultUserMsgs: function () {
    		this._msg = new Object();

            this._msg._contactingServer = "Contacting Mobage..."
			this._msg._networkError = "Sorry, a network error occured during the transaction.";
			//this._msg._InAppComment = "Titans vs Olympians purchase of %val1 gold";
			this._msg._authorizingPurchase = "Authorizing the purchase..";
			this._msg._completingTransaction = "Completing the transaction...";
			this._msg._cancellingTransaction = "Cancelling the transaction...";
			this._msg._itemNotFound = "Specified item not found, please contact customer service.";
			this._msg._insufficentFunds = "Sorry, you do not have enough Mobacoins.";
			this._msg._noButtonPressed = "Sorry, the purchase did not go through successfully."
			this._msg._serverUnauth = "Sorry, server did not authorize this purchase.";
    },
	
	_loadUserMsgs: function() {
		if(GALocalizationHandler != undefined) {
			if(GALocalizationHandler.getLocalizedString("inapp_contactingMobage") != "inapp_contactingMobage")		//keys are defined
			{
				this._msg._contactingServer = GALocalizationHandler.getLocalizedString("inapp_contactingMobage");
				this._msg._networkError = GALocalizationHandler.getLocalizedString("inapp_networkError");
				//this._msg._InAppComment = GALocalizationHandler.getLocalizedString("inapp_InAppCommentForTransaction");
				this._msg._authorizingPurchase = GALocalizationHandler.getLocalizedString("inapp_authorizingThePurchase");
				this._msg._completingTransaction = GALocalizationHandler.getLocalizedString("inapp_completingTransaction");
				this._msg._cancellingTransaction = GALocalizationHandler.getLocalizedString("inapp_cancellingTransaction");
				this._msg._itemNotFound = GALocalizationHandler.getLocalizedString("inapp_unableToPerformMobaKoinc");
				this._msg._insufficentFunds = GALocalizationHandler.getLocalizedString("inapp_insufficentBalance");
				this._msg._noButtonPressed = GALocalizationHandler.getLocalizedString("inapp_notAuthorize");
				this._msg._serverUnauth = GALocalizationHandler.getLocalizedString("inapp_unAuthServer");
			}
		}
	},
    
	_performInAppCallback: function(error, item) {	
		setTimeout(UIFactory.hideProgressHUD.bind(this), 3000);		//there is a slight delay in before the confirmation appears, these 3 seconds actually cover that span.
		if(!error)
        {
      		//var billingItems = [{"item" : { "id":item.id}, "quantity":"1"}];
			var billingItems = [{"item" : { "id":item.id}, "quantity":this._quantity}];
                                                                        									
			/*
				Do not show progress HUD as it will not let us click the OK button on in App confirmation.
				create a transaction with the above items, once you get the id in the call back you can perform further actions on the transaction
			*/
			
			Bank.Debit.createTransaction(billingItems, this._msg._InAppComment, this._createTransactionCallBack.bind(this));
			//this._completeTransaction();			
			//GAPurchaseSyncHandler.synchPendingTransactions(this.temp);
		}
        else
        {
			this._transactionFailure(error.errorCode)
		}
	},
	
	_createTransactionCallBack: function(error, transaction) {	
		UIFactory.showProgressHUD(this._msg._authorizingPurchase);
		console.log("zaki::: GA IN APP error is: "+JSON.stringify(error));
		console.log("zaki::: GA IN APP transaction is: "+JSON.stringify(transaction));
		if(!error) {			
			if(transaction) {				
				//user has pressed OKAY Button
				console.log("zaki:::: GOING TO PRESS OK BUTTON :");
				this._confirmedTransactionId = transaction.id;
				//now ask bank to open the transaction.
				Bank.Debit.openTransaction(this._confirmedTransactionId, this._openTransactionCallBack.bind(this));
			} else {
				//user has pressed NO Button
				//this._transactionFailure(GAInAppPurchase.noButton);
				this._transactionFailure(GAInAppPurchase.miscError);
			}
		} else {
		   var errorCode = GAInAppPurchase.miscError;
		   if(error == "usercanceled")  //spelling from mobage! do not change! you'll regret it afterwards. //you've been warned.
		   {
		         errorCode = GAInAppPurchase.noButton;
		   }
		   
		   this._transactionFailure(errorCode);
		}
	},
	
	addToCompletedTransactions: function(transactionId) {
		this._completedTransactions[transactionId] = "1";
		this._txnStorage.setItem(COMPLETED_TXN_KEY, JSON.stringify(this._completedTransactions));
	},
	
	hasBeenCompleted: function(transactionId) {
		if (this._completedTransactions != null && this._completedTransactions.length > 0) {
			var val = this._completedTransactions[transactionId];
			if (typeof val != 'undefined' && val == "1") {
				return true;
			}
		}
		return false;
	},
	
	_openTransactionCallBack: function(error,transaction) {		
		if(!error) {
			if(transaction) {
				//this._notifyGame();
				//this.addToCompletedTransactions(this._confirmedTransactionId);
				Bank.Debit.closeTransaction(this._confirmedTransactionId, this._closeTransactionCallBack.bind(this));
				UIFactory.showProgressHUD(this._msg._completingTransaction);
			} else {
				this._transactionFailure(GAInAppPurchase.miscError);
			}
		} else {
			//display alert box
			this._transactionFailure(error.errorCode);
		}
	},

	_closeTransactionCallBack: function(error, transaction) {
		if(!error) {
			if(transaction) {
				this._completeTransaction();
			} else {
				this._transactionFailure(GAInAppPurchase.miscError);
			}
		}
		else {
			this._transactionFailure(GAInAppPurchase.miscError);
		}
	},
	
	_transactionFailure: function(errorCode)
	{
		UIFactory.hideProgressHUD();
		UIFactory.showProgressHUD(this._msg._cancellingTransaction);
		var finalError = new Object();
		finalError.code = errorCode;
		finalError.showAlert = true;
		switch(errorCode) {
			case GAInAppPurchase.noButton:
				finalError.description = this._msg._noButtonPressed;
				break;
			case GAInAppPurchase.noFunds:
				finalError.description = this._msg._insufficentFunds;
				finalError.showAlert = false;
				break;
			case GAInAppPurchase.badServer:
				finalError.description = this._msg._serverUnauth;
				break;
			case GAInAppPurchase.noItem:
				finalError.description = this._msg._itemNotFound;
				break;
			default:
				finalError.description = this._msg._networkError;
				break;
		}
		this._cancelTransaction(finalError);
	},
	
	_cancelTransaction: function(anErrorMsg) {
		this._errorMsg = anErrorMsg;
        if(this._confirmedTransactionId) {
            Bank.Debit.cancelTransaction(this._confirmedTransactionId,this._cancelTransactionCallback.bind(this));
        }
        else {
            this._cancelTransactionCallback();
        }
	},
	
	_cancelTransactionCallback: function(error, transaction) {
		if(!error || !transaction || this._retryCount <= 0) {
			this._completeTransaction();
		}
		else {
			this._retryCount = this._retryCount - 1;
			Bank.Debit.cancelTransaction(this._confirmedTransactionId, this._cancelTransactionCallback.bind(this));
		}
	},
	
	_notifyGame: function() {
		/*if(this._errorMsg) {
			this._callBack(this._errorMsg);
		}
		else {
			this._callBack();
		}*/	
		this._callBack();
	},

	_completeTransaction: function() {
		UIFactory.hideProgressHUD();
		UIFactory.hideBlockView();
		if(this._errorMsg) {
			this._callBack(this._errorMsg);
		}
		else {
			this.addToCompletedTransactions(this._confirmedTransactionId);
			this._callBack();
		}
		setTimeout(this._initStatusVars.bind(this), 100);
	},
	
	_getRequestParams: function(currencyType, amount, signature) {
		var params = GACommonUtils.getServerParams();
		delete params[GA_UDID_PARAM_KEY];
		params["type"] = "userkey";
		params["snuid"] = GAConfigurations.getUserId();
		params["currencyType"] = currencyType;
		params["currency"] = amount;
		params["signature"] = signature;
		var queryString = [];
		for (var param in params) {
			var paramComponents = [];
			paramComponents.push(param);
			paramComponents.push("=");
			paramComponents.push(params[param]);
			queryString.push(paramComponents.join(""));
		}
		return queryString.join("&");
	},
	
	_getSignature: function(currencyType, amount) {
		var components = [];
		components.push(GAConfigurations.getUserId());
		components.push(currencyType);
		components.push(amount);
		components.push(GAConfigurations.getGameVersion());
		components.push(GAGameLoader.getResponseObject().getGame());
		components.push(GAINAPP_AUTHENTICATION_KEY);
		var str = components.join("");
		return Core.SHA1.hex_sha1(str);
	},
	
	_getRequestUrl: function(currencyType, amount, signature) {
		var requestUrl = [];
		requestUrl.push(GAConfigurations.getURL());
		requestUrl.push("inAppPurchased?");
		requestUrl.push(encodeURI(this._getRequestParams(currencyType, amount, signature)));
		return requestUrl.join("");
	},

    /* private delegate callbacks start */

	webFetchSuccess : function(webFetcher, responseData){
		if(webFetcher != null){
			webFetcher.destroy();
			webFetcher = null;
		}
		console.log("InApp Purchase: Server notification SUCCESSFUL!");
	},
	
	webFetchFailure : function(webFetcher, errorCode){
		if(webFetcher != null){
			webFetcher.destroy();
			webFetcher = null;
		}
		console.log("InApp Purchase: Server notification FAILED! Error code: " + errorCode);
	},
	
    /* private delegate callbacks end */
    
	destroy: function() {
		this._msg._contactingServer = null;
		this._msg._networkError = null;
		this._msg._InAppComment = null;
		this._msg._authorizingPurchase = null;
		this._msg._completingTransaction = null;
		this._msg._cancellingTransaction = null;
		this._msg._itemNotFound = null;
		this._msg._insufficentFunds = null;
		this._msg._noButtonPressed = null;
		this._msg._serverUnauth = null;
		this._msg = null;
		this._confirmedTransactionId = null;
		this._callBack = null;
		this._errorMsg = null;
		this._retryCount = 0;
		this._quantity = 0;
	}
});